
#include <avr/io.h>
#include <avr/interrupt.h>

#include "clock.h"
#include "usart.h"
#include "global.h"

#define BAUD 9600L

unsigned char nmea_buf[NMEA_BUF_SIZE];
unsigned int write_index;

#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)   // clever runden
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))     // Reale Baudrate
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD-1000) // Fehler in Promille 

#if ((BAUD_ERROR>10) || (BAUD_ERROR<-10))
   #error Systematischer Fehler der Baudrate grösser 1% und damit zu hoch! 
#endif


void USART_init()
{
        /* Set baud rate */
        UBRRH = UBRR_VAL >> 8;
        UBRRL = UBRR_VAL & 0xff;

        write_index = 0;

        /* Enable Receiver [and Transmitter] */
        UCSRB |= (1<<RXCIE) | (1<<RXEN); //|(1<<TXEN);

        /* 8N1 */
        UCSRC |= (1<<URSEL) | (3<<UCSZ0);

}


ISR(USART_RXC_vect)
{
        unsigned char dummy;

        ledGreenOn();

        if (UCSRA & (1 << RXC)) {
                if (UCSRA & (1 << FE) || UCSRA & (1 << DOR) || UCSRA & (1 << PE)) {
                        ledRedOn();
                        dummy = UDR;
                } else {
                        ledRedOff();
                        nmea_buf[write_index] = UDR;
                        write_index = ++write_index % NMEA_BUF_SIZE;
                }
        }

        ledGreenOff();
}


unsigned char USART_receive()
{
        unsigned char dummy;

        if (UCSRA & (1 << RXC)) {
                if (UCSRA & (1 << FE) || UCSRA & (1 << DOR) || UCSRA & (1 << PE)) {
                        dummy = UDR;
                } else {
                        return UDR;
                }
        }

        return 0;
}
